/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet.config.annotation;

import java.util.List;

import org.springframework.core.convert.converter.Converter;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

/**
 * 定义回调方法以自定义通过 {@code @EnableWebMvc} 启用的 Spring MVC 的基于 Java 的配置。
 *
 * <p>
 * {@code @EnableWebMvc}-注解的配置类可以实现这个接口以被回调并有机会自定义默认配置。
 */
public interface WebMvcConfigurer {

	/**
	 * 帮助配置 {@link HandlerMapping} 路径匹配选项，例如是否使用已解析的 {@code PathPatterns} 或与 {@code PathMatcher} 匹配的字符串模式，是否匹配尾部斜杠等。
	 * @since 4.0.3
	 * @see PathMatchConfigurer
	 */
	default void configurePathMatch(PathMatchConfigurer configurer) {
	}

	/**
	 * 配置内容协商选项。
	 */
	default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
	}

	/**
	 * 配置异步请求处理选项。
	 */
	default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
	}

	/**
	 * 配置处理程序以通过转发到 Servlet 容器的“默认”servlet 来委派未处理的请求。
	 * 一个常见的用例是当 {@link DispatcherServlet} 映射到 "" 从而覆盖 Servlet 容器对静态资源的默认处理时。
	 */
	default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
	}

	/**
	 * 除了默认注册的之外，添加 {@link Converter Converters} 和 {@link Formatter Formatters}。
	 */
	default void addFormatters(FormatterRegistry registry) {
	}

	/**
	 * 添加 Spring MVC 生命周期拦截器，用于控制器方法调用和资源处理程序请求的预处理和后处理。
	 * 可以注册拦截器以应用于所有请求或仅限于 URL 模式的子集。
	 */
	default void addInterceptors(InterceptorRegistry registry) {
	}

	/**
	 * 添加处理程序以从 Web 应用程序根目录、类路径等的特定位置提供静态资源，例如图像、js 和 css 文件。
	 * @see ResourceHandlerRegistry
	 */
	default void addResourceHandlers(ResourceHandlerRegistry registry) {
	}

	/**
	 * 配置跨源请求处理。
	 * @since 4.2
	 */
	default void addCorsMappings(CorsRegistry registry) {
	}

	/**
	 * 配置预先配置有响应状态代码和或视图的简单自动化控制器以呈现响应正文。
	 * 这在不需要自定义控制器逻辑的情况下很有用——例如呈现主页、执行简单的站点 URL 重定向、返回带有 HTML 内容的 404 状态、无内容的 204 状态等等。
	 * @see ViewControllerRegistry
	 */
	default void addViewControllers(ViewControllerRegistry registry) {
	}

	/**
	 * 配置视图解析器以将从控制器返回的基于字符串的视图名称转换为具体的 {@link org.springframework.web.servlet.View} 实现以执行渲染。
	 * @since 4.1
	 */
	default void configureViewResolvers(ViewResolverRegistry registry) {
	}

	/**
	 * 添加解析器以支持自定义控制器方法参数类型。
	 * <p>
	 * 这不会覆盖对解析处理程序方法参数的内置支持。要自定义对参数解析的内置支持，请直接配置 {@link RequestMappingHandlerAdapter}。
	 * @param resolvers initially an empty list
	 */
	default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
	}

	/**
	 * 添加处理程序以支持自定义控制器方法返回值类型。
	 * <p> 使用此选项不会覆盖对处理返回值的内置支持。要自定义处理返回值的内置支持，请直接配置 RequestMappingHandlerAdapter。
	 * @param handlers initially an empty list
	 */
	default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
	}

	/**
	 * 配置 {@link HttpMessageConverter HttpMessageConverters} 以用于读取或写入请求或响应的正文。如果没有添加转换器，则会注册一个默认的转换器列表。
	 * <p><strong>注意</strong> 将转换器添加到列表中会关闭默认转换器注册。要简单地添加转换器而不影响默认注册，请考虑使用该方法 {@link #extendMessageConverters(java.util.List)} 代替
	 * @param converters initially an empty list of converters
	 */
	default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
	}

	/**
	 * 配置后用于扩展或修改转换器列表的挂钩。
	 * 这可能很有用，例如允许注册默认转换器，然后通过此方法插入自定义转换器。
	 * @param converters the list of configured converters to extend.
	 * @since 4.1.3
	 */
	default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
	}

	/**
	 * 配置异常解析器。
	 * <p>给定的列表开始为空。
	 * 如果留空，框架会配置一组默认解析器，
	 * 请参阅 {@link WebMvcConfigurationSupportaddDefaultHandlerExceptionResolvers(List, org.springframework.web.accept.ContentNegotiationManager)}。
	 * 或者，如果将任何异常解析器添加到列表中，则应用程序有效地接管并且必须提供完全初始化的异常解析器。
	 * <p>或者，您可以使用
	 * {@link #extendHandlerExceptionResolvers(List)} 它允许您扩展或修改默认配置的异常解析器列表。
	 *
	 * @param resolvers initially an empty list
	 * @see #extendHandlerExceptionResolvers(List)
	 * @see WebMvcConfigurationSupport#addDefaultHandlerExceptionResolvers(List, org.springframework.web.accept.ContentNegotiationManager)
	 */
	default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
	}

	/**
	 * Extending or modify the list of exception resolvers configured by default.
	 * This can be useful for inserting a custom exception resolver without
	 * interfering with default ones.
	 * @param resolvers the list of configured resolvers to extend
	 * @since 4.3
	 * @see WebMvcConfigurationSupport#addDefaultHandlerExceptionResolvers(List, org.springframework.web.accept.ContentNegotiationManager)
	 */
	default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
	}

	/**
	 * Provide a custom {@link Validator} instead of the one created by default.
	 * The default implementation, assuming JSR-303 is on the classpath, is:
	 * {@link org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean}.
	 * Leave the return value as {@code null} to keep the default.
	 */
	@Nullable
	default Validator getValidator() {
		return null;
	}

	/**
	 * Provide a custom {@link MessageCodesResolver} for building message codes
	 * from data binding and validation error codes. Leave the return value as
	 * {@code null} to keep the default.
	 */
	@Nullable
	default MessageCodesResolver getMessageCodesResolver() {
		return null;
	}

}
